const http_placeholder = '127.0.0.1:5000'
const zeromq_placeholder = '127.0.0.1:5555'
const placeholder_prefix = ''
var modalWidth = 0
var modalHeight = 0
const FREQUENCY_updateServiceWait = 500
const MAX_RETRY_updateServiceWait = 10

const app = Vue.createApp({
    delimiters: ['[[', ']]'], // 更改分隔符，避免与 Handlebars 冲突
    data() {
        return {
            services_dict: {},
            searchQuery: '',
            showModal: false,
            isSubmitting: false,
            selectedCategory: null,  // 添加选中的分类
            newService: {
                protocol: 'http',  // 默认选择 HTTP
                address: '',
                name: '',
                category: ''
            },
            top: 0,
            left: 0,
            isDragging: false,
            offsetX: 0,
            offsetY: 0
        }
    },
    computed: {
        filteredServices() {
            const query = this.searchQuery.toLowerCase()
            const result = {}
            for (const [k, v] of Object.entries(this.services_dict)) {
                if ((!this.selectedCategory || 
                    this.selectedCategory === '所有' || 
                    (this.selectedCategory === '未分类' && (!v.category || v.category === '')) || 
                    v.category === this.selectedCategory) && 
                    (
                        v.name && v.name.toLowerCase().includes(query) ||
                        v.given_name && v.given_name.toLowerCase().includes(query) ||
                        v.address.toLowerCase().includes(query))) {
                    result[k] = v
                }
            }
            return result
        }
    },
    methods: {
        addr2id(addr) {
            return addr.replaceAll("/", "-").replaceAll(":", "+")
        },
        reset_update() {
            this.searchQuery = ''  // 清空搜索框
            this.$forceUpdate()    // 强制更新视图
        },
        no_reset_update() {
            this.$forceUpdate()    // 强制更新视图
        },
        getServiceNameDisplay(service) {
            if (service.given_name && service.name) {
                return service.given_name + '（' + service.name + '）'
            } else if (service.given_name) {
                return service.given_name
            } else {
                return service.name
            }
        },
        async loadServices() {
            try {
                const response = await fetch('/_/services/get')
                if (!response.ok) throw new Error('获取服务列表失败')
                this.services_dict = await response.json()
                for (const [k, v] of Object.entries(this.services_dict)) {
                    v.id = k
                    v.tasks = v.tasks.map(task => ({
                        signature: task,
                        selectedFile: null,
                        fileContent: null
                    }))
                }
                this.reset_update()
            } catch (error) {
                alert(error.message)
            }
        },
        showAddModal() {
            this.showModal = true
            // 如果当前选中的分类不是"所有"或"未分类"，则自动填入
            if (this.selectedCategory && this.selectedCategory !== '所有' && this.selectedCategory !== '未分类') {
                this.newService.category = this.selectedCategory
            }
        },
        closeModal() {
            this.showModal = false
            this.newService = {
                protocol: 'http',
                address: '',
                name: '',
                category: ''
            }
            this.resetModalPosition()
        },
        getAddressPlaceholder() {
            return (this.newService.protocol === 'http' 
                    ? http_placeholder
                    : zeromq_placeholder);
        },
        async submitService() {
            try {
                this.isSubmitting = true
                novel = {}
                novel.address = this.newService.protocol.toLowerCase() + '://' + this.newService.address
                novel.id = this.addr2id(novel.address)
                if (this.services_dict[novel.id]) {
                    alert('服务地址已存在: ' + novel.address)
                    return
                }
                novel.given_name = this.newService.given_name
                novel.category = this.newService.category
                novel.status = 'CannotReach'
                novel.status_temp = 'Loading'
                novel.tasks = [] // 初始化为空数组而不是null
                
                const response = await fetch('/_/services/add', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        address: novel.address,
                        given_name: novel.given_name,
                        category: novel.category,
                        description: "没有描述",
                        tasks: [],
                        workflows: [],
                    })
                })

                if (!response.ok) throw new Error('添加服务失败')
                
                this.closeModal()
                this.updateServiceWait(novel)
                this.services_dict[novel.id] = novel
                this.reset_update()
                // alert('服务添加成功')
            } catch (error) {
                alert(error.message)
            } finally {
                this.isSubmitting = false
            }
        },
        async deleteService(service) {
            if (!confirm('确定要删除此服务吗？')) return
            try {
                const response = await fetch(`/_/services/delete/${service.id}`, {
                    method: 'DELETE'
                })
                if (!response.ok) throw new Error('删除服务失败')
                delete this.services_dict[service.id]
                this.reset_update()
            } catch (error) {
                alert(error.message)
            }
        },
        async updateService(service) {
            try {
                console.log('try to get registered data: ', service.address)
                const response = await fetch(`/_/services/get/${service.id}`, {
                    method: 'GET',
                })
                if (!response.ok) throw new Error('获取服务失败')
                const updatedService = await response.json()
                updatedService.id = service.id
                if (updatedService.tasks && Array.isArray(updatedService.tasks)) {
                    updatedService.tasks = updatedService.tasks.map(task => ({
                        signature: task,
                        selectedFile: null,
                        fileContent: null
                    }))
                } else {
                    updatedService.tasks = []
                }
                if (service.category && (!updatedService.category || updatedService.category === '')) {
                    updatedService.category = service.category;
                }
                
                if (updatedService.status === 'CannotReach') {
                    console.log('无法连接到服务: ', service.address)
                }
                this.services_dict[service.id] = updatedService
                this.no_reset_update()
                return true
            } catch (error) {
                console.error(error.message)
                return false
            }
        },
        async updateServiceWait(service) {
            await new Promise(resolve => setTimeout(resolve, FREQUENCY_updateServiceWait))
            console.log('try to update service wait: ', service)
            let retry = 0
            while (retry < MAX_RETRY_updateServiceWait && !await this.updateService(service)) {
                this.no_reset_update()
                retry += 1
            }
            console.log('update service retry for', retry, 'times')
            this.services_dict[service.id].status_temp = null
            this.reset_update()
        },
        async refreshService(service) {
            try {
                const response = await fetch(`/_/services/refresh/${service.id}`, {
                    method: 'GET',
                })
                if (!response.ok) throw new Error('刷新服务失败')
                this.services_dict[service.id].status_temp = 'Loading'
                this.updateServiceWait(service)
            } catch (error) {
                console.error(error.message)
            }
        },
        async refreshAllServices() {
            await this.loadServices()
            for (const [k, v] of Object.entries(this.services_dict)) {
                if (v.status === 'CannotReach') {
                    await this.refreshService(v)
                }
            }
        },
        toggleService(service) {
            service.isExpanded = !service.isExpanded
        },
        getStatusClass(status) {
            const statusClasses = {
                'Running': 'badge-success',
                'CannotReach': 'badge-danger',
                'Mounted': 'badge-success',
                'Registered': 'badge-warning',
                'Loading': 'badge-info'
            }
            return statusClasses[status] || 'badge-secondary'
        },
        getCategoryClass(category) {
            const categoryClasses = {
                'calibration': 'badge-primary',
                'tracking': 'badge-secondary',
                'stimulus': 'badge-danger',
                'analysis': 'badge-warning',
                'visualization': 'badge-info',
                'modeling': 'badge-third',
                'strategy': 'badge-success',
                '所有': 'badge-danger',
                '未分类': 'badge-info',
            }
            return categoryClasses[category] || 'badge-basic'
        },
        getAllCategories() {
            // 收集所有存在的分类，过滤掉null和空字符串
            const existingCategories = Array.from(
                new Set(
                    Object.values(this.services_dict)
                        .map(service => service.category)
                        .filter(category => category && category !== '所有' && category !== '未分类')
                )
            );

            // 检查是否有未分类的服务
            const hasUncategorized = Object.values(this.services_dict).some(
                service => !service.category || service.category === ''
            );

            // 返回分类数组，总是包含"所有"，如果有未分类服务则包含"未分类"
            return ['所有', ...(hasUncategorized ? ['未分类'] : []), ...existingCategories];
        },
        startDrag(event) {
            this.isDragging = true
            this.offsetX = event.clientX - this.left
            this.offsetY = event.clientY - this.top
            document.addEventListener('mousemove', this.drag)
            document.addEventListener('mouseup', this.stopDrag)
        },
        drag(event) {
            if (!this.isDragging) return
            this.left = event.clientX - this.offsetX
            this.top = event.clientY - this.offsetY
        },
        stopDrag() {
            this.isDragging = false
            document.removeEventListener('mousemove', this.drag)
            document.removeEventListener('mouseup', this.stopDrag)
        },
        async handleFileSelect(event, service, task) {
            const file = event.target.files[0];
            if (!file) {
                return;
            }
            try {
                const content = await this.readFileContent(file);
                task.selectedFile = file.name;
                task.fileContent = content;
                this.no_reset_update();
            } catch (error) {
                alert('读取文件失败: ' + error.message);
            }
            event.target.value = '';
        },
        readFileContent(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = (e) => resolve(e.target.result);
                reader.onerror = (e) => reject(new Error('文件读取失败'));
                reader.readAsText(file);
            });
        },
        async startTask(service, task) {
            if (!task.fileContent && task.signature.split(':')[1].split('->')[0].trim() !== 'Void') {
                alert('请上传文件，因为任务需要输入参数。');
                return;
            }
            const data = {
                "service_id": service.id,
                "task_name": task.signature.split(':')[0],
                "input_file_content": task.fileContent || ''
            }
            try {
                const response = await fetch('/_/services/start_task', {
                    method: "POST",
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(data)
                });
                if (!response.ok) {
                    throw new Error('启动任务失败');
                }
            } catch(error) {
                alert(error.message)
            }
            this.no_reset_update()
        },
        selectFile(serviceId, taskIndex) {
            const fileInput = document.getElementById(`file-input-${serviceId}-${taskIndex}`);
            fileInput.click();
        },
        resetModalPosition() {
            const windowWidth = window.innerWidth
            const windowHeight = window.innerHeight
            const modalWidth = 600
            const modalHeight = 400
            this.top = (windowHeight - modalHeight) / 2
            this.left = (windowWidth - modalWidth) / 2
        },
        setSelectedCategory(category) {
            this.selectedCategory = this.selectedCategory === category ? null : category
        }
    },
    mounted() {
        this.loadServices()
        this.resetModalPosition()
        window.vue = this
    }
})

// 挂载 Vue 应用
app.mount('#app')
